#pragma once
#include "RpcRoutor.hpp"
#include "rpc_register.hpp"
#include "rpc_topic.hpp"
#include "../common/dispatcher.hpp"
#include "../client/rpc_client.hpp"

namespace bitrpc
{
    namespace server
    {
        // 注册中心服务端,只需要针对服务注册与服务发现请求进行处理即可
        class RegistryServer
        {
        public:
            using ptr = std::shared_ptr<RegistryServer>;
            RegistryServer(int port)
                : _pd_manager(std::make_shared<PDManager>()),
                  _dispatcher(std::make_shared<dispatcher>())
            {
                auto service_cb = std::bind(&PDManager::onServiceRequest, _pd_manager.get(),
                                            std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<ServiceRequest>(bitrpc::MessageType::REQ_SERVICE, service_cb);

                auto close_cb = std::bind(&RegistryServer::onConnShutdown, this,
                                          std::placeholders::_1);
                auto method = std::bind(&bitrpc::dispatcher::onMessage, _dispatcher.get(),
                                        std::placeholders::_1, std::placeholders::_2);

                _server = ServerFactory::create(port);
                _server->setMessageCallback(method);
                _server->setCloseCallback(close_cb);
            }
            void start()
            {
                _server->start();
            }

        private:
            void onConnShutdown(const BaseConnection::ptr &conn)
            {
                _pd_manager->onConnShutdown(conn);
            }

        private:
            PDManager::ptr _pd_manager; // 对提供者和发现者进行管理
            dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };

        class RpcServer
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;
            // RpcServer端有两套地址信息
            // 1.rpc服务提供端的地址信息，必须是服务器对外访问地址，（云服务器的监听地址和访问地址不同）
            // 2.注册中心服务端的地址信息，——启用服务注册后，连接注册中心服务端进行服务注册的
            RpcServer(const Address &access_addr, bool enableRegistry = false, const Address &registry_server = Address())
                : _access_addr(access_addr),
                  _enableRegistry(enableRegistry),
                  _dispatcher(std::make_shared<dispatcher>()),
                  _routor(std::make_shared<RpcRoutor>())
            {
                if (enableRegistry)
                {
                    _reg_client = std::make_shared<client::RegistryClient>(registry_server.first, registry_server.second);
                }

                auto rpc_cb = std::bind(&RpcRoutor::onMessage, _routor.get(),
                                        std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<RPCRequest>(bitrpc::MessageType::REQ_RPC, rpc_cb);

                auto method = std::bind(&bitrpc::dispatcher::onMessage, _dispatcher.get(),
                                        std::placeholders::_1, std::placeholders::_2);

                _server = ServerFactory::create(access_addr.second);
                _server->setMessageCallback(method);
            }
            void registerMethod(const ServiceDescribe::ptr &service)
            {
                _routor->Register(service);
                if (_enableRegistry)
                {
                    _reg_client->registryMethod(service->method(), _access_addr);
                }
            }
            void start()
            {
                _server->start();
            }

        private:
            bool _enableRegistry;
            Address _access_addr;
            client::RegistryClient::ptr _reg_client; // 服务注册客户端
            RpcRoutor::ptr _routor;
            dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };
        // 发布订阅服务端
        class TopicServer
        {
        public:
            using ptr = std::shared_ptr<TopicServer>;
            TopicServer(int port)
                : _topic_manager(std::make_shared<TopicManager>()),
                  _dispatcher(std::make_shared<dispatcher>())
            {
                auto service_cb = std::bind(&TopicManager::onTopicRequest, _topic_manager.get(),
                                            std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<TopicRequest>(bitrpc::MessageType::REQ_TOPIC, service_cb);

                auto close_cb = std::bind(&TopicServer::onConnShutdown, this,
                                          std::placeholders::_1);
                auto method = std::bind(&bitrpc::dispatcher::onMessage, _dispatcher.get(),
                                        std::placeholders::_1, std::placeholders::_2);

                _server = ServerFactory::create(port);
                _server->setMessageCallback(method);
                _server->setCloseCallback(close_cb);
            }
            void start()
            {
                _server->start();
            }

        private:
            void onConnShutdown(const BaseConnection::ptr &conn)
            {
                _topic_manager->onShutDown(conn);
            }

          

        private:
            TopicManager::ptr _topic_manager;
            dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };
    }

}